package com.gdteam.kernel.i18n.impl;

import java.io.InputStream;
import java.net.URL;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import org.apache.tapestry5.ioc.annotations.EagerLoad;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.annotations.Symbol;
import org.slf4j.Logger;

import com.gdteam.kernel.conf.Environment;
import com.gdteam.kernel.i18n.I18nManager;
import com.gdteam.kernel.util.ClasspathUtil;

@EagerLoad
public class DefaultI18nManager implements I18nManager {

    private Locale currentLocale;
    
    private String resourceFolderPath;
    
    private List<String> baseNameList = new ArrayList<String>();
    private List<ResourceBundle> currentResources = new ArrayList<ResourceBundle>();

    private Logger logger;
    
    public DefaultI18nManager(@Inject @Symbol(Environment.I18N_RESOURCE_FOLDER) String resourceFolderPath, Logger logger) {
        try {
            
            this.resourceFolderPath = resourceFolderPath;
            
            if (resourceFolderPath == null) {
                throw new Exception("You must specify resource folder name for localized resources");
            }
            
            URL folderURL = DefaultI18nManager.class.getClassLoader().getResource(resourceFolderPath);
            
            if (folderURL == null) {
                throw new Exception("Cannot find " + this.resourceFolderPath +" in classpath");
            }
            
            String[] resourceList = ClasspathUtil.getResourceListing(this.getClass(), this.resourceFolderPath + "/");
            
            for (String resourceName : resourceList) {
                
                //File must be like MyResources_de_CH or MyResources_de (no _ in base name)
                String baseName = resourceName.substring(0, resourceName.indexOf("_")); 
                
                if (!baseNameList.contains(baseName)) {
                    baseNameList.add(baseName);
                }   
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        this.setCurrentLocale(Locale.getDefault());
    }
    
    public Locale getCurrentLocale() {
        return this.currentLocale;
    }

    public void setCurrentLocale(Locale locale) {
        this.currentLocale = locale;
        
        this.currentResources.clear();
        
        for (String baseName : this.baseNameList) {
            this.currentResources.add(ResourceBundle.getBundle(baseName, locale));
        }
    }
    
    /**
     * Get bundle resource for specified locale
     * @param baseName
     * @param locale
     * @return bundle resource for specified locale
     */
    private ResourceBundle getResourceBundle(String baseName, Locale locale) {
        return ResourceBundle.getBundle(baseName, locale);
    }


    public String getLocalizedString(String key) {
        
        for (ResourceBundle resourceBundle : this.currentResources) {
            try {
                String ret = resourceBundle.getString(key);
                return ret;
            } catch (Exception e) {
                //Do nothing
            }
        }
        return "key not found";
    }


    public DecimalFormatSymbols getLocalizedDecimalFormatSymbols() {
        return new DecimalFormatSymbols(this.currentLocale);
    }


    public InputStream getLocalizedFile(String baseDir, String baseName, String extension) {
        
        StringBuilder languageCountryPath = new StringBuilder(baseDir).append("/").append(baseName);
        languageCountryPath.append("_").append(this.currentLocale.getLanguage());
        languageCountryPath.append("_").append(this.currentLocale.getCountry());
        languageCountryPath.append(".").append(extension);
        
        InputStream is = this.getClass().getClassLoader().getResourceAsStream(languageCountryPath.toString());
        
        if (is != null) {
            return is;
        }
        
        StringBuilder countryPath = new StringBuilder(baseDir).append("/").append(baseName);
        countryPath.append("_").append(this.currentLocale.getLanguage());
        languageCountryPath.append(".").append(extension);
        
        is = this.getClass().getClassLoader().getResourceAsStream(countryPath.toString());
        
        if (is != null) {
            return is;
        }
        
        StringBuilder defaultPath = new StringBuilder(baseDir).append("/").append(baseName);
        defaultPath.append(".").append(extension);
        
        is = this.getClass().getClassLoader().getResourceAsStream(defaultPath.toString());
        
        if (is != null) {
            return is;
        }
        
        StringBuilder errorMessage = new StringBuilder("Cannot find any localized file in classpath :");
        errorMessage.append("\n        - ").append(languageCountryPath.toString());
        errorMessage.append("\n        - ").append(countryPath.toString());
        errorMessage.append("\n        - ").append(defaultPath.toString());
        
        throw new IllegalArgumentException(errorMessage.toString());
    }


    public InputStream getLocalizedFile(String baseName, String extension) {
        return this.getLocalizedFile(null, baseName, extension);
    }
    
}
